#ifndef CONN_EVENT_H_
#define CONN_EVENT_H_

#ifdef __cplusplus
extern "C" {
#endif

#include "evconnsvrd.h"

/* connection status */
enum EConnStatus
{
	connev_status_none,
	connev_status_wait_syn,
	connev_status_wait_ack,
	connev_status_in_queue,
	connev_status_wait_server_res,
	connev_status_connected,
};

/* notify type */
enum ENotifyType{
	connev_notify_none = 0,
	connev_notify_server = 1,
	connev_notify_client_version_fail = 2,
	connev_notify_client_server_disconn = 4,
	connev_notify_client_timeout_fail = 8,
};

typedef struct connev_t
{
	struct list_head waiting;
	struct event* ev;
	struct connbuffer_t* in_buffer;
	struct connbuffer_t* out_buffer;
	char peer_addr[32];
	char self_addr[32];
	int32_t status;
	int32_t encrypt_key;
	int32_t address;
	int32_t notify_type;
}connev_t;

/* create a new connection event */
struct connev_t* connev_init(evutil_socket_t sock_fd, int32_t connbuffer_size);

/* reset connection event, ensure to call it after remove from reactor event base */
void connev_reset(struct connev_t* connev);

/* re-init reset connection event */
void connev_reinit(struct connev_t* connev, evutil_socket_t sock_fd);

/* destruct connection-event, remove from reactor, recycle resource */
void connev_destruct(struct connev_t* connev, int32_t notify_type);

/* release connection event resource */
void connev_release(struct connev_t* connev);

const char* connev_peer_addr(struct connev_t* connev);
const char* connev_self_addr(struct connev_t* connev);

int32_t connev_add(struct connev_t* connev);
int32_t connev_del(struct connev_t* connev);

/* update register events */
void connev_update_event(struct connev_t* connev, short events);

/* event callback */
void connev_callback(evutil_socket_t fd, short event, void* args);

/* 
*  write data to connection event buffer 
*  return = 0 success
*  return < 0 fail
*/
int32_t connev_write(struct connev_t* connev, const char* buffer, size_t buffer_len);

/*
* return < 0, connev destructed
*/
int32_t connev_timeout_cb(struct connev_t* connev);

/*
* return < 0, connev destructed
*/
int32_t connev_read_cb(struct connev_t* connev);

/*
* return < 0, connev destructed
*/
int32_t connev_write_cb(struct connev_t* connev);

int32_t connev_hash(const void* ev);
int32_t connev_cmp(const void* ev1, const void* ev2);

struct connev_pool_t* connev_pool_init(int connbuffer_size, int threshold_hint);

void connev_pool_release(struct connev_pool_t* pool);

/* allocate a connection-event from pool and init */
struct connev_t* connev_pool_alloc_init(struct connev_pool_t* pool, evutil_socket_t sock_fd);

void connev_pool_free(struct connev_pool_t* pool, struct connev_t* connev);

#ifdef __cplusplus
}
#endif

#endif // CONN_EVENT_H_


